﻿/// <reference path="libs/jquery-2.0.2.js" />
/// <reference path="prototypeExtensions.js" />

var GameObject = Object.create({
    init: function () {
    }
});

var Figure = GameObject.extend({
    init: function (x0, y0, rotationCode) {
        this._super.init();
        this.x0 = x0;
        this.y0 = y0;
        this.rotationCode = rotationCode;
    },

    initCoords: function () {
    }
});

var Dash = Figure.extend({
    init: function (x0, y0, rotationCode) {
        this._super.init(arguments);
        this.type = "dash";
        this.color = "blue";
        this.coords = this.initCoords();
    },

    initCoords: function () {
        return [
            [
                [0, 0, 0, 0], [1, 1, 1, 1], [0, 0, 0, 0], [1, 1, 1, 1]
            ],
            [
                [0, 1, 0, 0], [0, 1, 0, 0], [0, 1, 0, 0], [0, 1, 0, 0]
            ],
            [
                [0, 0, 0, 0], [1, 1, 1, 1], [0, 0, 0, 0], [1, 1, 1, 1]
            ],
            [
                [0, 1, 0, 0], [0, 1, 0, 0], [0, 1, 0, 0], [0, 1, 0, 0]
            ],
        ];
    }
});



//var Dash = $.inherit(Figure, {
//    __constructor: function (xCentral, yCentral, currentRotationCode) {
//        this.type = "dash";
//        this.x0 = xCentral;
//        this.y0 = yCentral;
//        this.currentRotation = currentRotationCode;
//        this.coords = this.InitCoords();
//        this.color = "blue";
//    },
//    InitCoords: function () {
//        var currentCoords = [3];

//        if (this.currentRotation === 0) {
//            currentCoords = [{ x: this.x0, y: this.y0 },
//                    { x: this.x0, y: this.y0 - 40 },
//                    { x: this.x0, y: this.y0 + 40 }];
//        }
//        else if (this.currentRotation === 1) {
//            currentCoords = [{ x: this.x0, y: this.y0 },
//                    { x: this.x0 - 40, y: this.y0 },
//                    { x: this.x0 + 40, y: this.y0 }];
//        }

//        return currentCoords;
//    }
//});

var ZElement = $.inherit(Figure, {
    __constructor: function (xCentral, yCentral, currentRotationCode) {
        this.type = "zElement";
        this.x0 = xCentral;
        this.y0 = yCentral;
        this.currentRotation = currentRotationCode;
        this.coords = this.InitCoords();
        this.color = "blue";
    },
    InitCoords: function () {
        var currentCoords = [4];

        if (this.currentRotation === 0) {
            currentCoords = [{ x: this.x0, y: this.y0 },
                    { x: this.x0 - 40, y: this.y0 },
                    { x: this.x0, y: this.y0 + 40 },
                    { x: this.x0 + 40, y: this.y0 + 40 }];
        }
        else if (this.currentRotation === 1) {
            currentCoords = [{ x: this.x0, y: this.y0 },
                    { x: this.x0 - 40, y: this.y0 },
                    { x: this.x0, y: this.y0 - 40 },
                    { x: this.x0 - 40, y: this.y0 + 40 }];
        }

        return currentCoords;
    }
});

var SElement = $.inherit(Figure, {
    __constructor: function (xCentral, yCentral, currentRotationCode) {
        this.type = "sElement";
        this.x0 = xCentral;
        this.y0 = yCentral;
        this.currentRotation = currentRotationCode;
        this.coords = this.InitCoords();
        this.color = "blue";
    },
    InitCoords: function () {
        var currentCoords = [4];

        if (this.currentRotation === 0) {
            currentCoords = [{ x: this.x0, y: this.y0 },
                    { x: this.x0 + 40, y: this.y0 },
                    { x: this.x0, y: this.y0 + 40 },
                    { x: this.x0 - 40, y: this.y0 + 40 }];
        }
        else if (this.currentRotation === 1) {
            currentCoords = [{ x: this.x0, y: this.y0 },
                    { x: this.x0 - 40, y: this.y0 },
                    { x: this.x0, y: this.y0 + 40 },
                    { x: this.x0 - 40, y: this.y0 - 40 }];
        }

        return currentCoords;
    }
});

var TElement = $.inherit(Figure, {
    __constructor: function (xCentral, yCentral, currentRotationCode) {
        this.type = "tElement";
        this.x0 = xCentral;
        this.y0 = yCentral;
        this.currentRotation = currentRotationCode;
        this.coords = this.InitCoords();
        this.color = "blue";
    },
    InitCoords: function () {
        var currentCoords = [4];

        if (this.currentRotation === 0) {
            currentCoords = [{ x: this.x0, y: this.y0 },
                    { x: this.x0 - 40, y: this.y0 },
                    { x: this.x0 + 40, y: this.y0 },
                    { x: this.x0, y: this.y0 + 40 }];
        }
        else if (this.currentRotation === 1) {
            currentCoords = [{ x: this.x0, y: this.y0 },
                    { x: this.x0 - 40, y: this.y0 },
                    { x: this.x0, y: this.y0 - 40 },
                    { x: this.x0, y: this.y0 + 40 }];

        }
        else if (this.currentRotation === 2) {
            currentCoords = [{ x: this.x0, y: this.y0 },
                    { x: this.x0 - 40, y: this.y0 },
                    { x: this.x0 + 40, y: this.y0 },
                    { x: this.x0, y: this.y0 - 40 }];
        }
        else if (this.currentRotation === 3) {
            currentCoords = [{ x: this.x0, y: this.y0 },
                    { x: this.x0, y: this.y0 - 40 },
                    { x: this.x0, y: this.y0 + 40 },
                    { x: this.x0 + 40, y: this.y0 }];
        }
        return currentCoords;
    }
});

var Angle = $.inherit(Figure, {
    __constructor: function (xCentral, yCentral, currentRotationCode) {
        this.type = "angle";
        this.x0 = xCentral;
        this.y0 = yCentral;
        this.currentRotation = currentRotationCode;
        this.coords = this.InitCoords();
        this.color = "blue";
    },
    InitCoords: function () {
        var currentCoords = [3];

        if (this.currentRotation === 0) {
            currentCoords = [{ x: this.x0, y: this.y0 },
                    { x: this.x0 + 40, y: this.y0 },
                    { x: this.x0, y: this.y0 + 40 }];
        }
        else if (this.currentRotation === 1) {
            currentCoords = [{ x: this.x0, y: this.y0 },
                    { x: this.x0 - 40, y: this.y0 },
                    { x: this.x0, y: this.y0 + 40 }];
        }
        else if (this.currentRotation === 2) {
            currentCoords = [{ x: this.x0, y: this.y0 },
                    { x: this.x0 - 40, y: this.y0 },
                    { x: this.x0, y: this.y0 - 40 }];
        }
        else if (this.currentRotation === 3) {
            currentCoords = [{ x: this.x0, y: this.y0 },
                    { x: this.x0 + 40, y: this.y0 },
                    { x: this.x0, y: this.y0 - 40 }];
        }
        return currentCoords;
    }
});

var LongAngle = $.inherit(Figure, {
    __constructor: function (xCentral, yCentral, currentRotationCode) {
        this.type = "longAngle";
        this.x0 = xCentral;
        this.y0 = yCentral;
        this.currentRotation = currentRotationCode;
        this.coords = this.InitCoords();
        this.color = "blue";
    },
    InitCoords: function () {
        var currentCoords = [4];

        if (this.currentRotation === 0) {
            currentCoords = [{ x: this.x0, y: this.y0 },
                    { x: this.x0 + 40, y: this.y0 },
                    { x: this.x0, y: this.y0 + 40 },
                    { x: this.x0, y: this.y0 + 80 }];
        }
        else if (this.currentRotation === 1) {
            currentCoords = [{ x: this.x0, y: this.y0 },
                    { x: this.x0 - 40, y: this.y0 },
                    { x: this.x0, y: this.y0 + 40 },
                    { x: this.x0 - 80, y: this.y0 }];
        }
        else if (this.currentRotation === 2) {
            currentCoords = [{ x: this.x0, y: this.y0 },
                    { x: this.x0 - 40, y: this.y0 },
                    { x: this.x0, y: this.y0 - 40 },
                    { x: this.x0, y: this.y0 - 80 }];
        }
        else if (this.currentRotation === 3) {
            currentCoords = [{ x: this.x0, y: this.y0 },
                    { x: this.x0 + 40, y: this.y0 },
                    { x: this.x0, y: this.y0 - 40 },
                    { x: this.x0 + 80, y: this.y0 }];
        }

        return currentCoords;
    }
});

var Square = $.inherit(Figure, {
    __constructor: function (xCentral, yCentral) {
        this.type = "square";
        this.x0 = xCentral;
        this.y0 = yCentral;
        this.currentRotation = 0;
        this.coords = this.InitCoords();
        this.color = "blue";
    },
    InitCoords: function () {
        var currentCoords = [3];
        currentCoords = [{ x: this.x0, y: this.y0 },
                         { x: this.x0 + 40, y: this.y0 },
                         { x: this.x0, y: this.y0 + 40 },
                         { x: this.x0 + 40, y: this.y0 + 40 }];
        return currentCoords;
    }
});

var Cell = $.inherit(GameUnit, {
    __constructor: function (x, y, status) {
        this.x = x;
        this.y = y;
        this.color = "white";
        this.isBusy = status;
        this.isBorder = false;
    }
});

var GameField = $.inherit(GameUnit, {
    __constructor: function () {
        _that = this;
        this.field = this.InitField();
        this.setFallingFiguresInterval();
        this.InitKeyFunctionality();
        this.typesOfFigures = Array("angle", "square", "dash", "zElement", "tElement", "sElement", "longAngle");
        this.downDirection = 0;
        this.rotationCode = 0;  //* 0-> stay, 1-> 90degree, 2-> 180degree, 3-> 270degree
        this.horizontalDirection = 80;
        this.leftGameFieldBorder = 40;
        this.rightGameFieldBorder = 320; //TODO: FIX
        this.bottomGameFieldBorder = 360;
        //this.score = 0; //* counter for deleted rows
        this.render();
        this.fullRowsCounter = 0;
    },
    InitField: function () {
        var field = [10];
        for (var n = 0; n < 10; n++) {
            field[n] = [10];
            for (var v = 0; v < 10; v++) {
                var currentCell = new Cell(n * 40, v * 40, false);
                field[n][v] = currentCell;
            }
        }
        return field;
    },
    render: function () {
        for (var p = 0; p < 10; p++) {
            for (var m = 0; m < 10; m++) {
                var currentCell = document.createElement("div");
                currentCell.style.position = "absolute";
                currentCell.style.width = 40 + "px";
                currentCell.style.height = 40 + "px";
                currentCell.style.top = p * 40 + "px";
                currentCell.style.left = m * 40 + "px";
                currentCell.style.backgroundColor = this.field[p][m].color;
                var currentCellJQuery = $(currentCell); //* casts to jQuery element

                $("#wrapper").append(currentCellJQuery);
            }
        }
    },
    setFallingFiguresInterval: function () {
        var placedFigures = [];
        var currentFigure; //= new Angle; //* always start game with this figure
        createdFigure = "angle";
        var isScoreUpdated = false;

        setInterval(function () {
            var changedCells = [];

            //* --------------------------------update new coordinates--------------------------------
            if (createdFigure === "angle") {
                currentFigure = new Angle(_that.downDirection, _that.horizontalDirection, _that.rotationCode);
            }
            else if (createdFigure === "square") {
                currentFigure = new Square(_that.downDirection, _that.horizontalDirection);
            }
            else if (createdFigure === "sElement") {
                currentFigure = new SElement(_that.downDirection, _that.horizontalDirection, _that.rotationCode);
            }
            else if (createdFigure === "zElement") {
                currentFigure = new ZElement(_that.downDirection, _that.horizontalDirection, _that.rotationCode);
            }
            else if (createdFigure === "tElement") {
                currentFigure = new TElement(_that.downDirection, _that.horizontalDirection, _that.rotationCode);
            }
            else if (createdFigure === "dash") {
                currentFigure = new Dash(_that.downDirection, _that.horizontalDirection, _that.rotationCode);
            }
            else if (createdFigure === "longAngle") {
                currentFigure = new LongAngle(_that.downDirection, _that.horizontalDirection, _that.rotationCode);
            }
            //currentFigure.init(_that.downDirection, _that.horizontalDirection, _that.rotationCode);

            //* --------------------check if is bottom reached, for all busy cells------------------------
            var isBottomLevelReached = false;
            var lowerReachedCellsCoords = []; //* gets the lowest coord of the point of the figure


            var lenLowerReached = currentFigure.coords.length;
            for (var t = 0; t < lenLowerReached; t++) {             //* each point of the figure
                for (var z = 0; z < 10; z++) {                      //* each row of the game field
                    for (var h = 0; h < 10; h++) {                  //* each col of the game field
                        if ((currentFigure.coords[t].x === _that.field[z][h].x)
                            && (currentFigure.coords[t].y === _that.field[z][h].y)) {

                            if (z < 9) {
                                if (_that.field[z + 1][h].isBusy || _that.field[z + 1][h].isBorder) {
                                    isBottomLevelReached = true;
                                    var newCoordsToCheck = { xlower: z, ylower: h };
                                    lowerReachedCellsCoords.push(newCoordsToCheck);
                                }
                            }
                            else if (z === 9) {
                                isBottomLevelReached = true;
                                var newCoordsToCheck = { xlower: z, ylower: h };
                                lowerReachedCellsCoords.push(newCoordsToCheck);
                            }
                            else if (_that.field[z][h].isBusy || _that.field[z + 1][h].isBorder) { //* if bottom reached (collision with busy cell)
                                isBottomLevelReached = true;
                                var newCoordsToCheck = { xlower: z, ylower: h };
                                lowerReachedCellsCoords.push(newCoordsToCheck);
                            }
                        }
                    }
                }
            }


            var lowerBusyReachedPoint = { xlower: 0, ylower: 0 };
            for (var ii = 0; ii < lowerReachedCellsCoords.length; ii++) {
                if (lowerReachedCellsCoords[ii].xlower > lowerBusyReachedPoint.xlower) {
                    lowerBusyReachedPoint = {
                        xlower: lowerReachedCellsCoords[ii].xlower,
                        ylower: lowerReachedCellsCoords[ii].ylower
                    };
                }
            }

            //*----------------------mark figure cells-------------------
            var len = currentFigure.coords.length;
            for (var i = 0; i < len; i++) {             //* each point of the figure
                for (var j = 0; j < 10; j++) {          //* each row of the game field
                    for (var k = 0; k < 10; k++) {      //* each col of the game field
                        if ((currentFigure.coords[i].x === _that.field[j][k].x)
                            && (currentFigure.coords[i].y === _that.field[j][k].y)) {
                            _that.field[j][k].color = currentFigure.color;
                            changedCells.push({ row: j, col: k });

                            if (j === 9) {
                                _that.field[j][k].isBorder = true; //* makes the bottom cells busy by default
                            }
                        }
                    }
                }
            }

            //*--------------------delete everything in wrapper and render again------------
            $("#wrapper").html('');
            _that.render();

            //*-------------------restart field cells with color yellow to red----------------
            for (var r = 0, changedCellsLen = changedCells.length; r < changedCellsLen; r++) {
                _that.field[changedCells[r].row][changedCells[r].col].isBusy = false;
                _that.field[changedCells[r].row][changedCells[r].col].color = "white";
            }

            //*----------------------------save placed figure-----------------------------------
            if (isBottomLevelReached) {
                var figureToPlace;
                if (createdFigure === "angle") {
                    figureToPlace = new Angle(_that.downDirection, _that.horizontalDirection, _that.rotationCode);
                }
                else if (createdFigure === "square") {
                    figureToPlace = new Square(_that.downDirection, _that.horizontalDirection, _that.rotationCode);
                }
                else if (createdFigure === "sElement") {
                    figureToPlace = new SElement(_that.downDirection, _that.horizontalDirection, _that.rotationCode);
                }
                else if (createdFigure === "zElement") {
                    figureToPlace = new ZElement(_that.downDirection, _that.horizontalDirection, _that.rotationCode);
                }
                else if (createdFigure === "tElement") {
                    figureToPlace = new TElement(_that.downDirection, _that.horizontalDirection, _that.rotationCode);
                }
                else if (createdFigure === "dash") {
                    figureToPlace = new Dash(_that.downDirection, _that.horizontalDirection, _that.rotationCode);
                }
                else if (createdFigure === "longAngle") {
                    figureToPlace = new LongAngle(_that.downDirection, _that.horizontalDirection, _that.rotationCode);
                }

                placedFigures.push(figureToPlace);

                _that.downDirection = -40; //* restart direction

                _that.rotationCode = 0; //* restart rotation

                //* -----------------choose random figure------------------
                var currentTypeFigure = _that.typesOfFigures[Math.floor(Math.random()
                                        * _that.typesOfFigures.length)]

                if (currentTypeFigure === "angle") { //* TODO: of cases for all types of figures
                    createdFigure = "angle";
                }
                if (currentTypeFigure === "sElement") { //* TODO: of cases for all types of figures
                    createdFigure = "sElement";
                }
                if (currentTypeFigure === "zElement") { 
                    createdFigure = "zElement";
                }
                if (currentTypeFigure === "tElement") { 
                    createdFigure = "tElement";
                }
                if (currentTypeFigure === "dash") { 
                    createdFigure = "dash";
                }
                if (currentTypeFigure === "square") { 
                    createdFigure = "square";
                }
                if (currentTypeFigure === "longAngle") { 
                    createdFigure = "longAngle";
                }
            }

            //*-------------------Mark placed figures in the bottom with BUSY and appropriate color-----------
            for (var f = 0, len = placedFigures.length; f < len; f++) {
                var placedFigure = placedFigures[f];

                for (var g = 0, length = placedFigure.coords.length; g < length; g++) {
                    _that.field[(placedFigure.coords[g].x) / 40][(placedFigure.coords[g].y) / 40].isBusy = true;
                    _that.field[(placedFigure.coords[g].x) / 40][(placedFigure.coords[g].y) / 40].color =
                        currentFigure.color;
                }
            }

            _that.downDirection += 40; //* updates movement down direction

            //* -------------------------check for full rows to delete-----------------------------
            if (isBottomLevelReached) {
                _that.fullRowsCounter = 0;
                for (var row = 9; row >= 0; row--) {        //* check all rows starting from bottom
                    var isFullRow = true;
                    for (var col = 0; col < 10; col++) {
                        if (_that.field[row][col].isBusy === false) {
                            isFullRow = false;
                        }
                    }

                    if (isFullRow) {
                        // TODO: add some qjuery effects
                        for (var fr = 0; fr < 10; fr++) { //* for all cells in the current full row
                            _that.field[row][fr].isBusy = false; //* delete current row that is full
                            _that.field[row][fr].color = "white";
                        }
                        //TODO: MOVE ALL CELL ABOVE WITH ONE POSITION DOWN DIRECTION
                        _that.fullRowsCounter += 1;

                        if (_that.fullRowsCounter * 10 > _that.score) {
                            isScoreUpdated = false;
                        }

                        if (!isScoreUpdated) {
                            currentScore += 10;
                            //_that.score += 10; //* increase score
                            //TODO: SOME SPECIAL EFFECTS HERE (FADE IN DADE OUT..../ANIMATION)
                            alert("Congrats u have full row! \n Your score: " + currentScore);
                            $('#score').text("Score: " + currentScore);
                            isScoreUpdated = true;
                        }
                    }
                }
            }

        }, 500);
    },
    InitKeyFunctionality: function () {
        $(window).keypress(function (e) {
            var pressedKeyCode = e.which;
            //alert(pressedKeyCode);
            if (pressedKeyCode === 32) {
                _that.rotationCode += 1;
                if (_that.rotationCode >= 4) {
                    _that.rotationCode = 0;
                }
            }
            else if (pressedKeyCode === 97) { //* A pressed - moves left
                if (_that.horizontalDirection != _that.leftGameFieldBorder) {
                    _that.horizontalDirection -= 40;
                }

            }
            else if (pressedKeyCode === 100) { //* D pressed - moves right
                if (_that.horizontalDirection != _that.rightGameFieldBorder) {
                    _that.horizontalDirection += 40;
                }
            }
        });
    }
});